package bservice

import (
	// "encoding/json"
	// "fmt"
	"strings"
	"sync"
	"time"

	"advertoper/db"
	"advertoper/errorcode"

	"doubimeizhi.com/datatable"
	"doubimeizhi.com/utility"

	log "github.com/cihub/seelog"
)

var (
	defaultBannerManageService *BannerManageService
)

type BannerManageService struct {
	bannerDatainfo map[int]*BannerDataItem
	bannerDataLock *sync.RWMutex
	bannerMaxId    int
}

func newBannerManageService() *BannerManageService {
	service := &BannerManageService{}
	service.bannerDatainfo = make(map[int]*BannerDataItem)
	service.bannerDataLock = new(sync.RWMutex)
	service.bannerMaxId = 0
	service.loadDataInit() //load数据
	return service
}

func GetBannerManageService() *BannerManageService {
	if defaultBannerManageService == nil {
		defaultBannerManageService = newBannerManageService()
	}
	return defaultBannerManageService
}

//添加
type BannerDataAdd struct {
	ClickAble           int    `json:"clickable"`   //1:可点击,2:不可点击
	ServerCode          string `json:"server_code"` //运营位编号
	Channel             string `json:"channel"`     //渠道
	Title               string `json:"title"`
	PicUrl              string `json:"pic_url"`
	Routers             string `json:"routers"`
	RegionCode          string `json:"region_code"`
	StartTick           int64  `json:"starttick"`
	EndTick             int64  `json:"endtick"`
	AndroidStartVersion int    `json:"android_start_version"`
	AndroidEndVersion   int    `json:"android_end_version"`
	IosStartVersion     int    `json:"ios_start_version"`
	IosEndVersion       int    `json:"ios_end_version"`
}

//修改
type BannerDataUpdate struct {
	BannerDataAdd
	Id     int `json:"id"`
	Status int `json:"status"`
}

//缓存数据
type BannerDataItem struct {
	BannerDataUpdate
	InsertTick int64 `json:"insert_tick"`
	UpdateTick int64 `json:"update_tick"`
}

//查询list
type BannerDataList struct {
	Id                  int    `json:"id"`
	ServerCode          string `json:"server_code"` //运营位编号
	Channel             string `json:"channel"`     //渠道
	ClickAble           int    `json:"clickable"`   //1:可点击,2:不可点击
	Title               string `json:"title"`
	PicUrl              string `json:"pic_url"`
	Routers             string `json:"routers"`
	Status              int    `json:"status"`
	RegionCode          string `json:"region_code"`
	AndroidStartVersion int    `json:"android_start_version"`
	AndroidEndVersion   int    `json:"android_end_version"`
	IosStartVersion     int    `json:"ios_start_version"`
	IosEndVersion       int    `json:"ios_end_version"`
	StartTick           string `json:"starttick"` //展示的时候展示字符串时间
	EndTick             string `json:"endtick"`   //展示的时候展示字符串时间
	InsertTime          string `json:"insert_time"`
	UpdateTime          string `json:"update_time"`
}

//客户端查
type BannerDataUserListReq struct {
	Ids         []int
	RegionCode  string
	ServerCode  string
	Channel     string
	Plat        string
	VersionCode int
}
type BannerDataUserList struct {
	Id        int    `json:"id"`
	ClickAble int    `json:"clickable"` //1:可点击,2:不可点击
	Title     string `json:"title"`
	PicUrl    string `json:"pic_url"`
	Routers   string `json:"routers"`
}

//load数据缓存
func (p *BannerManageService) loadDataInit() {
	daq := datatable.NewDataTableQuery()
	daq.SetTableName("operation_banner_data")
	daq.PushField(&datatable.FiledItem{Alias: "id", Field: "id"})
	daq.PushField(&datatable.FiledItem{Alias: "server_code", Field: "server_code"})
	daq.PushField(&datatable.FiledItem{Alias: "region_code", Field: "region_code"})
	daq.PushField(&datatable.FiledItem{Alias: "channel", Field: "channel"})
	daq.PushField(&datatable.FiledItem{Alias: "android_start_version", Field: "android_start_version"})
	daq.PushField(&datatable.FiledItem{Alias: "android_end_version", Field: "android_end_version"})
	daq.PushField(&datatable.FiledItem{Alias: "ios_start_version", Field: "ios_start_version"})
	daq.PushField(&datatable.FiledItem{Alias: "ios_end_version", Field: "ios_end_version"})
	daq.PushField(&datatable.FiledItem{Alias: "clickable", Field: "clickable"})
	daq.PushField(&datatable.FiledItem{Alias: "title", Field: "title"})
	daq.PushField(&datatable.FiledItem{Alias: "pic_url", Field: "pic_url"})
	daq.PushField(&datatable.FiledItem{Alias: "routers", Field: "routers"})
	daq.PushField(&datatable.FiledItem{Alias: "starttick", Field: "starttick"})
	daq.PushField(&datatable.FiledItem{Alias: "endtick", Field: "endtick"})
	daq.PushField(&datatable.FiledItem{Alias: "insert_tick", Field: "insert_tick"})
	daq.PushField(&datatable.FiledItem{Alias: "update_tick", Field: "update_tick"})
	daq.PushField(&datatable.FiledItem{Alias: "status", Field: "status"})
	sql, values := daq.GenerateSQL()
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	results, err := mysqlHelper.Query(sql, values...)
	if err != nil {
		log.Errorf("load all banner data fail ,~~~init(),err is %s", err.Error())
		return
	}
	p.bannerDataLock.Lock()
	defer p.bannerDataLock.Unlock()
	for _, dt := range results {
		item := &BannerDataItem{}
		item.Id = mysqlHelper.GetColInt(dt, "id")
		item.RegionCode = mysqlHelper.GetColString(dt, "region_code")
		item.ServerCode = mysqlHelper.GetColString(dt, "server_code")
		item.Channel = mysqlHelper.GetColString(dt, "channel")
		item.AndroidStartVersion = mysqlHelper.GetColInt(dt, "android_start_version")
		item.AndroidEndVersion = mysqlHelper.GetColInt(dt, "android_end_version")
		item.IosStartVersion = mysqlHelper.GetColInt(dt, "ios_start_version")
		item.IosEndVersion = mysqlHelper.GetColInt(dt, "ios_end_version")
		item.ClickAble = mysqlHelper.GetColInt(dt, "clickable")
		item.Title = mysqlHelper.GetColString(dt, "title")
		item.PicUrl = mysqlHelper.GetColString(dt, "pic_url")
		item.Routers = mysqlHelper.GetColString(dt, "routers")
		item.StartTick = mysqlHelper.GetColInt64(dt, "starttick")
		item.EndTick = mysqlHelper.GetColInt64(dt, "endtick")
		item.InsertTick = mysqlHelper.GetColInt64(dt, "insert_tick")
		item.UpdateTick = mysqlHelper.GetColInt64(dt, "update_tick")
		item.Status = mysqlHelper.GetColInt(dt, "status")

		if item.Id > p.bannerMaxId {
			p.bannerMaxId = item.Id
		}
		//加入缓存
		p.bannerDatainfo[item.Id] = item
	}
	log.Infof("load BannerData data,len is :%d", len(p.bannerDatainfo))
}

//添加数据
func (p *BannerManageService) BannerAdd(req *BannerDataAdd) (uint, string) {
	if req.EndTick < req.StartTick {
		return 1002, "失效时间不能小于开始有效时间"
	}
	p.bannerDataLock.Lock()
	defer p.bannerDataLock.Unlock()
	//保存
	nowTime := time.Now().Unix()
	p.bannerMaxId += 1

	data := make(map[string]*utility.MySQLFieldValue)
	data["id"] = utility.NewMySQLFieldValue(p.bannerMaxId, false)
	data["region_code"] = utility.NewMySQLFieldValue(req.RegionCode, false)
	data["server_code"] = utility.NewMySQLFieldValue(req.ServerCode, false)
	data["channel"] = utility.NewMySQLFieldValue(req.Channel, false)
	data["android_start_version"] = utility.NewMySQLFieldValue(req.AndroidStartVersion, false)
	data["android_end_version"] = utility.NewMySQLFieldValue(req.AndroidEndVersion, false)
	data["ios_start_version"] = utility.NewMySQLFieldValue(req.IosStartVersion, false)
	data["ios_end_version"] = utility.NewMySQLFieldValue(req.IosEndVersion, false)
	data["clickable"] = utility.NewMySQLFieldValue(req.ClickAble, false)
	data["title"] = utility.NewMySQLFieldValue(req.Title, false)
	data["pic_url"] = utility.NewMySQLFieldValue(req.PicUrl, false)
	data["routers"] = utility.NewMySQLFieldValue(req.Routers, false)
	data["starttick"] = utility.NewMySQLFieldValue(req.StartTick, false)
	data["endtick"] = utility.NewMySQLFieldValue(req.EndTick, false)
	data["insert_tick"] = utility.NewMySQLFieldValue(nowTime, false)
	data["update_tick"] = utility.NewMySQLFieldValue(nowTime, false)
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	_, err := mysqlHelper.SaveRecord(data, "operation_banner_data")
	if err != nil {
		log.Errorf("insert banner fail ,~~~BannerAdd,err is %s", err.Error())
		return errorcode.EC_GL_INTERNAL_ERROR, errorcode.Msg(errorcode.EC_GL_INTERNAL_ERROR)
	}
	//添加缓存
	item := &BannerDataItem{}
	item.Id = p.bannerMaxId
	item.RegionCode = req.RegionCode
	item.ServerCode = req.ServerCode
	item.Channel = req.Channel
	item.AndroidStartVersion = req.AndroidStartVersion
	item.AndroidEndVersion = req.AndroidEndVersion
	item.IosStartVersion = req.IosStartVersion
	item.IosEndVersion = req.IosEndVersion
	item.ClickAble = req.ClickAble
	item.Title = req.Title
	item.PicUrl = req.PicUrl
	item.Routers = req.Routers
	item.StartTick = req.StartTick
	item.EndTick = req.EndTick
	item.InsertTick = nowTime
	item.UpdateTick = nowTime
	item.Status = 1

	p.bannerDatainfo[p.bannerMaxId] = item

	return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS)
}

//修改数据
func (p *BannerManageService) BannerUpdate(req *BannerDataUpdate) (uint, string) {
	//获取缓存数据
	oldData, ok := p.bannerDatainfo[req.Id]
	if !ok {
		return 101, "row is not invalid"
	}
	currDate := &BannerDataItem{}
	//将老的数据copy一份
	currDate.Id = oldData.Id
	currDate.ServerCode = oldData.ServerCode
	currDate.Channel = oldData.Channel
	currDate.AndroidStartVersion = oldData.AndroidStartVersion
	currDate.AndroidEndVersion = oldData.AndroidEndVersion
	currDate.IosStartVersion = oldData.IosStartVersion
	currDate.IosEndVersion = oldData.IosEndVersion
	currDate.EndTick = oldData.EndTick
	currDate.InsertTick = oldData.InsertTick
	currDate.PicUrl = oldData.PicUrl
	currDate.RegionCode = oldData.RegionCode
	currDate.Routers = oldData.Routers
	currDate.StartTick = oldData.StartTick
	currDate.Status = oldData.Status
	currDate.Title = oldData.Title
	currDate.UpdateTick = oldData.UpdateTick
	currDate.ClickAble = oldData.ClickAble

	updaq := datatable.NewDataTableUpdate()
	updaq.SetTableName("operation_banner_data")

	if req.RegionCode != "" {
		updaq.SetUpdateValue("region_code=?", req.RegionCode)
		currDate.RegionCode = req.RegionCode
	}
	if req.ServerCode != "" {
		updaq.SetUpdateValue("server_code=?", req.ServerCode)
		currDate.ServerCode = req.ServerCode
	}
	if req.Channel != "" {
		updaq.SetUpdateValue("channel=?", req.Channel)
		currDate.Channel = req.Channel
	}
	if req.AndroidStartVersion != 0 {
		updaq.SetUpdateValue("android_start_version=?", req.AndroidStartVersion)
	}
	if req.AndroidEndVersion != 0 {
		updaq.SetUpdateValue("android_end_version=?", req.AndroidEndVersion)
	}
	if req.IosStartVersion != 0 {
		updaq.SetUpdateValue("ios_start_version=?", req.IosStartVersion)
	}
	if req.IosEndVersion != 0 {
		updaq.SetUpdateValue("ios_end_version=?", req.IosEndVersion)
	}
	if req.ClickAble != 0 {
		updaq.SetUpdateValue("clickable=?", req.ClickAble)
		currDate.ClickAble = req.ClickAble
	}
	if req.Title != "" {
		if req.Title == "null" { //标题参数有带，需要为"",则传"null"
			req.Title = ""
		}
		updaq.SetUpdateValue("title=?", req.Title)
		currDate.Title = req.Title
	}
	if req.PicUrl != "" {
		updaq.SetUpdateValue("pic_url=?", req.PicUrl)
		currDate.PicUrl = req.PicUrl
	}
	if req.Routers != "" {
		updaq.SetUpdateValue("routers=?", req.Routers)
		currDate.Routers = req.Routers
	}
	if req.StartTick != 0 {
		updaq.SetUpdateValue("starttick=?", req.StartTick)
		currDate.StartTick = req.StartTick
	}
	if req.EndTick != 0 {
		updaq.SetUpdateValue("endtick=?", req.EndTick)
		currDate.EndTick = req.EndTick
	}
	if req.Status != 0 {
		if req.Status != 1 && req.Status != -1 {
			req.Status = 1
		}
		updaq.SetUpdateValue("status=?", req.Status)
		currDate.Status = req.Status
	}

	nowTime := time.Now().Unix()
	updaq.SetUpdateValue("update_tick=?", nowTime)
	currDate.UpdateTick = nowTime

	updaq.PushCondition("id=?", req.Id)

	sql, values := updaq.GenerateSQL()
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	_, err := mysqlHelper.Exec(sql, values...)
	if err != nil {
		log.Errorf("update banner fail ,~~~BannerUpdate,err is %s", err.Error())
		return errorcode.EC_GL_INTERNAL_ERROR, errorcode.Msg(errorcode.EC_GL_INTERNAL_ERROR)
	}
	//更新缓存
	p.bannerDatainfo[req.Id] = currDate

	return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS)
}

//web查询数据
func (p *BannerManageService) BannerWebList(status int, serverCode string) []*BannerDataList {
	if status != 1 && status != -1 {
		status = 1
	}
	data := make([]*BannerDataList, 0)
	//遍历缓存取数据
	for _, value := range p.bannerDatainfo {
		item := &BannerDataList{}
		if value.Status == status {
			if serverCode == "all" || value.ServerCode == serverCode {
				item.Id = value.Id
				item.ServerCode = value.ServerCode
				item.Channel = value.Channel
				item.AndroidStartVersion = value.AndroidStartVersion
				item.AndroidEndVersion = value.AndroidEndVersion
				item.IosStartVersion = value.IosStartVersion
				item.IosEndVersion = value.IosEndVersion
				item.ClickAble = value.ClickAble
				item.PicUrl = value.PicUrl
				item.RegionCode = value.RegionCode
				item.Routers = value.Routers
				item.Status = value.Status
				item.Title = value.Title
				item.InsertTime = time.Unix(value.InsertTick, 0).Format("2006-01-02 15:04:05")
				item.UpdateTime = time.Unix(value.UpdateTick, 0).Format("2006-01-02 15:04:05")
				item.StartTick = time.Unix(value.StartTick, 0).Format("2006-01-02 15:04:05")
				item.EndTick = time.Unix(value.EndTick, 0).Format("2006-01-02 15:04:05")

				data = append(data, item)
			}

		}
	}
	return data
}

//客户端查询数据
func (p *BannerManageService) UserGetBannerList(req *BannerDataUserListReq) []*BannerDataUserList {
	data := make([]*BannerDataUserList, 0)
	//遍历找到满足id的数据
	for _, dt := range req.Ids {
		for key, value := range p.bannerDatainfo {
			if key == dt {
				//当id满足，判断运营编号是否一致
				if req.ServerCode != value.ServerCode {
					continue
				}
				//过滤掉时间失效、人工置为无效、区域限制、渠道限制数据
				nowtick := time.Now().Unix()
				if value.StartTick <= nowtick && value.EndTick >= nowtick && value.Status == 1 &&
					IsRegionCode(value.RegionCode, req.RegionCode) &&
					IsChannel(value.Channel, req.Channel) {
					//过滤版本号
					if req.Plat == "android" {
						if value.AndroidStartVersion > req.VersionCode || value.AndroidEndVersion < req.VersionCode {
							continue
						}
					}
					if req.Plat == "ios" {
						if value.IosStartVersion > req.VersionCode && value.IosEndVersion < req.VersionCode {
							continue
						}
					}
					item := &BannerDataUserList{}
					item.Id = value.Id
					item.ClickAble = value.ClickAble
					item.PicUrl = value.PicUrl
					item.Routers = value.Routers
					item.Title = value.Title

					data = append(data, item)
				}
			}
		}
	}
	return data

}

func IsRegionCode(DataRegionCode, UserRegionCode string) bool {
	regionCode := strings.Split(DataRegionCode, ",")
	ok := false
	for _, dt := range regionCode {
		if dt == "all" || dt == UserRegionCode {
			ok = true
			break
		}
	}
	return ok
}

func IsChannel(dataChannel, userChannel string) bool {
	channel := strings.Split(dataChannel, ",")
	ok := false
	for _, dt := range channel {
		if dt == "all" || dt == userChannel {
			ok = true
			break
		}
	}
	return ok
}
